package com.bj58.ecdata.mailreport.util;

import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.TreeMap;

import com.bj58.ecdata.mailreport.db.CommonDao;
import com.bj58.groupbuy.action.util.MyStore;

public class CommonDataDeal {
	private CommonDao comDao = new CommonDao();
	private ReflectUtil reflectUtil = new ReflectUtil();
	private MyStore myStore = new MyStore();
	
	/**根据VO,将每条SQL查询出来的指标,按照统一查询维度进行组装
	 * @param <T>
	 * @param sqlMap  
	 * 	key:SQL+DB标记(SQL结尾加以数据库标记，以:号隔开，如SQL:1)
	 * 		如下：1.团购库   2.infobright   3.团购17从库   4.团购本地测试库   5.27 竞争对手库   6.二手库   
	 * 				  7. 统计库:58stat库  8.黄页库  9.团购线上测试库   10.广告库  11.shop库  12.精准库  13.数据字典库  
	 *       		  14.  从库14团购库   15. 数据17从库_精准  16.在线收入库
	 * 	value:此SQL查询的指标名  
	 * 
	 * @param clazz   vo对象
	 * @param gbList 维度字段集合
	 * @return
	 * @throws Exception
	 */
	@SuppressWarnings("static-access")
	public <T>List<T> AssembledDataBySqlMap(Map<String,List<String>> sqlMap,Class<T> clazz,List<String> gbList)throws Exception{
		
		//结果Map  根据gbList中的字段对应的值拼装作为KEY  各值以，号隔开
		TreeMap<String,T>  rsMap = new TreeMap<String,T>();
		
		/** 1.迭代所有的SQL，根据查询字段，查出对应的指标数据
		 *   2.迭代结果集 根据gbList存放的字段为KEY，查出是否已存在此KEY的对象数据
		 *   3.如无此KEY，则直接PUT   
		 *   4.此KEY已存在,则将此结果中的字段值，放入已存在对象中的对应字段
		 *   5.多个SQL查询同一个字段值,则将各SQL查出的值进行SUM
		 */
		for(Iterator<String> it = sqlMap.keySet().iterator(); it.hasNext();){
			String rSql = it.next();  //SQL+DB
			List<String> searchColList =sqlMap.get(rSql); //查询字段
			
			String searchSql = rSql.split(":")[0];
			int dbType  = Integer.parseInt(rSql.split(":")[1].trim());
			List<T> rsList = comDao.getCommonStatList(searchSql, searchColList, clazz, dbType);
			
			for(T vo : rsList){
				String key = getKeyValue(gbList, vo, clazz);
				
				if(key.contains("旅游度假")){ 
					key = key.replace("旅游度假", "旅游酒店");
				}
				
				if(rsMap.containsKey(key)){
					T newVo = rsMap.get(key);
					for(String searchCol : searchColList){
						if(gbList.contains(searchCol)){
							continue;
						}
						Field  field =  clazz.getDeclaredField(searchCol);
						Method getMethod = reflectUtil.getGetterMethod(clazz, field);
						Method setMethod = reflectUtil.getSetterMethod(clazz, field);
						
						Class<?> filedCls = field.getType();
						Object columnValueObj = null;
						if(filedCls == int.class || filedCls == Integer.class) {
							int a = Integer.parseInt(getMethod.invoke(vo).toString())  ;
							int b = Integer.parseInt(getMethod.invoke(newVo).toString());
							columnValueObj = (Object)(a + b);
						}else if(filedCls == long.class || filedCls == Long.class){
							long a = Long.parseLong(getMethod.invoke(vo).toString())  ;
							long b = Long.parseLong(getMethod.invoke(newVo).toString());
							columnValueObj = (Object)(a + b);
						}else if(filedCls == double.class || filedCls == Double.class){
							double a = Double.parseDouble(getMethod.invoke(vo).toString());
							double b = Double.parseDouble(getMethod.invoke(newVo).toString());
							columnValueObj = (Object)(a + b);
						}else{
							columnValueObj = getMethod.invoke(vo);
						}
						
						setMethod.invoke(newVo, new Object[] { columnValueObj });
					}
				}else{
					rsMap.put(key, vo);
				}
			}
		}
		//最终数据集  
		List<T> rsList = new ArrayList<T>();
		for(Iterator<String> it = rsMap.keySet().iterator(); it.hasNext();){
			String key = it.next();
			rsList.add(rsMap.get(key));
		}
		return rsList;
	}
	

	/**根据VO,将每条SQL查询出来的指标,按照统一查询维度进行组装
	 * @param <T>
	 * @param sqlMap  
	 * 	key:SQL+DB标记(SQL结尾加以数据库标记，以:号隔开，如SQL:1)
	 * 		如下：1.团购库   2.infobright   3.团购17从库   4.团购本地测试库   5.27 竞争对手库   6.二手库   
	 * 				  7. 统计库:58stat库  8.黄页库  9.团购线上测试库   10.广告库  11.shop库  12.精准库  13.数据字典库  
	 *       		  14.  从库14团购库   15. 数据17从库_精准  16.在线收入库
	 * 	value:此SQL查询的指标名  
	 * 
	 * @param clazz   vo对象
	 * @param gbList 维度字段集合
	 * @return
	 * @throws Exception
	 */
	@SuppressWarnings("static-access")
	public <T> Map<String,T> getDataMapBySqlMap(Map<String,List<String>> sqlMap,Class<T> clazz,List<String> gbList)throws Exception{
		
		//结果Map  根据gbList中的字段对应的值拼装作为KEY  各值以，号隔开
		TreeMap<String,T>  rsMap = new TreeMap<String,T>();
		
		for(Iterator<String> it = sqlMap.keySet().iterator(); it.hasNext();){
			String rSql = it.next();  //SQL+DB
			List<String> searchColList =sqlMap.get(rSql); //查询字段
			
			String searchSql = rSql.split(":")[0];
			int dbType  = Integer.parseInt(rSql.split(":")[1].trim());
			List<T> rsList = comDao.getCommonStatList(searchSql, searchColList, clazz, dbType);
			
			for(T vo : rsList){
				String key = getKeyValue(gbList, vo, clazz);
				
				if(key.contains("旅游度假")){ 
					key = key.replace("旅游度假", "旅游酒店");
				}
				
				if(rsMap.containsKey(key)){
					T newVo = rsMap.get(key);
					for(String searchCol : searchColList){
						if(gbList.contains(searchCol)){
							continue;
						}
						Field  field =  clazz.getDeclaredField(searchCol);
						Method getMethod = reflectUtil.getGetterMethod(clazz, field);
						Method setMethod = reflectUtil.getSetterMethod(clazz, field);
						
						Class<?> filedCls = field.getType();
						Object columnValueObj = null;
						if(filedCls == int.class || filedCls == Integer.class) {
							int a = Integer.parseInt(getMethod.invoke(vo).toString())  ;
							int b = Integer.parseInt(getMethod.invoke(newVo).toString());
							columnValueObj = (Object)(a + b);
						}else if(filedCls == long.class || filedCls == Long.class){
							long a = Long.parseLong(getMethod.invoke(vo).toString())  ;
							long b = Long.parseLong(getMethod.invoke(newVo).toString());
							columnValueObj = (Object)(a + b);
						}else if(filedCls == double.class || filedCls == Double.class){
							double a = Double.parseDouble(getMethod.invoke(vo).toString());
							double b = Double.parseDouble(getMethod.invoke(newVo).toString());
							columnValueObj = (Object)(a + b);
						}else{
							columnValueObj = getMethod.invoke(vo);
						}
						
						setMethod.invoke(newVo, new Object[] { columnValueObj });
					}
				}else{
					rsMap.put(key, vo);
				}
			}
		}
		//最终数据集  
		return rsMap;
	}
	
	
	/**将多组已查询出各自指标的对象集合，根据查询维度再次拼装
	 * @param <T>
	 * @param ObjectList
	 * @param clazz
	 * @param gbList
	 * @return
	 * @throws Exception
	 */
	@SuppressWarnings("static-access")
	public <T>List<T> AssembledDataByObjectList(Map<String,List<T>> ObjectMap,Class<T> clazz,List<String> gbList)throws Exception{
		//结果Map  根据gbList中的字段对应的值拼装作为KEY  各值以，号隔开
		TreeMap<String,T>  rsMap = new TreeMap<String,T>();
		/** 
		 *   2.迭代结果集 根据gbList存放的字段为KEY，查出是否已存在此KEY的对象数据
		 *   3.如无此KEY，则直接PUT   
		 *   4.此KEY已存在,则将此结果中的字段值，放入已存在对象中的对应字段
		 */
		for(Iterator<String> it = ObjectMap.keySet().iterator(); it.hasNext();){
			String searchCols = it.next();
			List<T> rsList = ObjectMap.get(searchCols);
			
			for(T vo : rsList){
				String key = getKeyValue(gbList, vo, clazz);
				
				if(key.contains("旅游度假")){ //类别不一致...
					key = key.replace("旅游度假", "旅游酒店");
				}
				
				if(rsMap.containsKey(key)){
					T newVo = rsMap.get(key);
					for(String searchCol : searchCols.split(",")){
						if(gbList.contains(searchCol)){
							continue;
						}
						Field  field =  clazz.getDeclaredField(searchCol);
						Method getMethod = reflectUtil.getGetterMethod(clazz, field);
						Method setMethod = reflectUtil.getSetterMethod(clazz, field);
						Object columnValueObj = getMethod.invoke(vo);
						setMethod.invoke(newVo, new Object[] { columnValueObj });
					}
				}else{
					rsMap.put(key, vo);
				}
			}
		}
		//最终数据集  
		List<T> rsList = new ArrayList<T>();
		for(Iterator<String> it = rsMap.keySet().iterator(); it.hasNext();){
			String key = it.next();
			rsList.add(rsMap.get(key));
		}
		return rsList;
	}
	
	
	/**获取组合KEY值
	 * @param <T>
	 * @param gbList
	 * @param vo
	 * @param clazz
	 * @return
	 */
	@SuppressWarnings("static-access")
	private <T>String getKeyValue (List<String> gbList,T vo,Class<?> clazz)throws Exception{
		StringBuffer key = new StringBuffer();
		
		for(int i = 0 ; i < gbList.size() ; i++){
			String gbValue = gbList.get(i);
			String value = "";
			if(null == reflectUtil.getGetterMethod(clazz, clazz.getDeclaredField(gbValue)).invoke(vo)){
				value ="";
			}else{
				 value = reflectUtil.getGetterMethod(clazz, clazz.getDeclaredField(gbValue)).invoke(vo).toString();
			}
			key.append(value);
			if(i != (gbList.size() - 1))
				key.append(",");
			
		}
		
		return key.toString();
	}
	
	/**根据cate2Id 和 cate1Id 填充对应的业务线字段
	 * @param <T>
	 * @param cate1IdName    vo中cate1字段名
	 * @param cate2IdName    vo中cate2字段名
	 * @param businessTypeName  vo中业务线字段名
	 * @param showType   1=展现类别  2=归属类别
	 * @param productType  1 = 用户业务线   2 = 商业业务线
	 * @throws Exception
	 */
	@SuppressWarnings("static-access")
	public <T>List<T> getbusinessTypeByCateId(List<T> rsList, Class<T> clazz ,String cate1IdName,String cate2IdName,String businessTypeName ,int showType , int productType)throws Exception{
		HashMap<Long, String> cateBusiMap = new HashMap<Long, String>(); //cateid-业务线 对应关系MAP
		if(showType == 1){
			cateBusiMap = myStore.getDispCateBusiMap(productType);
		}else if(showType == 2){
			cateBusiMap = myStore.getBelongCateBusiMap(productType);
		}
		
		for(T vo : rsList){
			String businessType = "null";
			Method businessTypeSetMethod = reflectUtil.getSetterMethod(clazz, clazz.getDeclaredField(businessTypeName));
			//先获取cate2id
			Method cate2GetMethod = reflectUtil.getGetterMethod(clazz,  clazz.getDeclaredField(cate2IdName));
			long cateId = Long.valueOf(cate2GetMethod.invoke(vo).toString()); 
			
			if( 0 == cateId){ //cate2id为0则取cate1id
				Method cate1GetMethod = reflectUtil.getGetterMethod(clazz,  clazz.getDeclaredField(cate1IdName));
				cateId = Long.valueOf(cate1GetMethod.invoke(vo).toString());
			}
			
			if(cateBusiMap.containsKey(cateId)){
				businessType = cateBusiMap.get(cateId);
			}
			
			businessTypeSetMethod.invoke(vo, new Object[] { businessType });
		}
		
		return rsList;
	}
	
}
